home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
tcp_ip
/
jnos
/
jnos_src
/
ksubr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-26
|
13KB
|
432 lines
/* Machine or compiler-dependent portions of kernel
* Turbo-C version for PC
* Copyright 1991 Phil Karn, KA9Q
*/
#ifdef MSDOS
#include <dos.h>
#endif
#include "global.h"
#include "proc.h"
#ifndef UNIX
#include "pc.h"
#endif
#include "commands.h"
#include "socket.h"
#ifdef MSDOS
char *Taskers[] = {
"",
"DoubleDos",
"DesqView",
"Windows",
"DOS 5/6",
"OS/2 DOS",
"DPMI"
};
static oldNull;
/* Template for contents of jmp_buf in Turbo C */
struct env {
unsigned sp;
unsigned ss;
unsigned flag;
unsigned cs;
unsigned ip;
unsigned bp;
unsigned di;
unsigned es;
unsigned si;
unsigned ds;
};
#endif
#ifdef UNIX
/*
* There are several different ways to implement jmp_buf's. We use macros to
* extract the fields. Note that these must expand into lvalues, because we
* load them during process initialization. Current code only uses _SP and
* _PC; this may change.
*
* I should fold the DOS code into this, but then I need to worry about
* segments. No thanks.
*/
#ifdef M_UNIX
/*
* I am unsure of these; the i386 contents are not documented in 3.2.2. I
* guessed at them by comparing "info regs" with the contents of a jmp_buf
* immediately after a setjmp().
*/
#define _PC(p) (p->env[5])
#define _SP(p) (p->env[4])
#define _BP(p) (p->env[3])
#endif
#ifdef linux
#define _PC(p) (p->env->__pc)
#define _SP(p) (p->env->__sp)
#define _BP(p) (p->env->__bp)
#endif
#endif
#ifndef UNIX
static int chkintstk __ARGS((void));
#endif
void
kinit()
{
#ifndef UNIX
int i;
/* Initialize interrupt stack for high-water-mark checking */
for(i=0;i<512;i++)
Intstk[i] = STACKPAT;
/* Remember location 0 pattern to detect null pointer derefs */
oldNull = *(unsigned short *)NULL;
#endif
}
/* Print process table info
* Since things can change while ps is running, the ready proceses are
* displayed last. This is because an interrupt can make a process ready,
* but a ready process won't spontaneously become unready. Therefore a
* process that changes during ps may show up twice, but this is better
* than not having it showing up at all.
*/
int
ps(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register struct proc *pp;
#ifndef UNIX
register struct env *ep;
#endif
int i;
#ifdef UNIX
tprintf("Uptime %s",tformat(secclock()));
#else
tprintf("Uptime %s Stack %x max intstk %u psp %04x",tformat(secclock()),
getss(),chkintstk(),_psp);
if(Mtasker != 0){
tprintf("\nRunning under %s",Taskers[Mtasker]);
}
#endif
tputs("\n");
#ifdef UNIX
tputs("PID SP maxstk stksize event fl in out name\n");
for (pp = Susptab; pp != NULLPROC; pp = pp->next)
{
if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %c%c%c %3d %3d %s\n",
pp, _SP(pp), pp->stksize, stkutil(pp), pp->event,
pp->i_state ? 'I' : ' ',
(pp->state & WAITING) ? 'W' : ' ',
(pp->state & SUSPEND) ? 'S' : ' ',
pp->input, pp->output, pp->name) == EOF)
return 0;
}
for (i = 0; i < PHASH; i++)
{
for (pp = Waittab[i]; pp != NULLPROC; pp = pp->next)
{
if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %c%c%c %3d %3d %s\n",
pp, _SP(pp), pp->stksize, stkutil(pp),
pp->event,
pp->i_state ? 'I' : ' ',
(pp->state & WAITING) ? 'W' : ' ',
(pp->state & SUSPEND) ? 'S' : ' ',
pp->input, pp->output, pp->name) == EOF)
return 0;
}
}
for (pp = Rdytab; pp != NULLPROC; pp = pp->next)
{
if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %c%c%c %3d %3d %s\n",
pp, _SP(pp), pp->stksize, stkutil(pp),
pp->event,
pp->i_state ? 'I' : ' ',
(pp->state & WAITING) ? 'W' : ' ',
(pp->state & SUSPEND) ? 'S' : ' ',
pp->input, pp->output, pp->name) == EOF)
return 0;
}
if( Curproc != NULLPROC)
{
if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %c%c%c %3d %3d %s\n",
Curproc, _SP(Curproc), Curproc->stksize,
stkutil(Curproc), Curproc->event,
Curproc->i_state ? 'I' : ' ',
(Curproc->state & WAITING) ? 'W' : ' ',
(Curproc->state & SUSPEND) ? 'S' : ' ',
Curproc->input, Curproc->output,
Curproc->name) == EOF)
return 0;
}
#else /* UNIX */
tputs("PID SP maxstk stksize event fl in out name\n");
for(pp = Susptab;pp != NULLPROC;pp = pp->next){
ep = (struct env *)&pp->env;
if(tprintf("%4.4x %-10lx%-10u%-10u%-10lx%c%c%c %3d %3d %s\n",
FP_SEG(pp),
ptol(MK_FP(ep->ss,ep->sp)),
pp->stksize,
stkutil(pp),
ptol(pp->event),
pp->i_state ? 'I' : ' ',
(pp->state & WAITING) ? 'W' : ' ',
(pp->state & SUSPEND) ? 'S' : ' ',
pp->input, pp->output,
pp->name) == EOF)
return 0;
}
for(i=0;i<PHASH;i++){
for(pp = Waittab[i];pp != NULLPROC;pp = pp->next){
ep = (struct env *)&pp->env;
if(tprintf("%4.4x %-10lx%-10u%-10u%-10lx%c%c%c %2d %2d %s\n",
FP_SEG(pp),ptol(MK_FP(ep->ss,ep->sp)),pp->stksize,stkutil(pp),
ptol(pp->event),
pp->i_state ? 'I' : ' ',
(pp->state & WAITING) ? 'W' : ' ',
(pp->state & SUSPEND) ? 'S' : ' ',
pp->input,pp->output,
pp->name) == EOF)
return 0;
}
}
for(pp = Rdytab;pp != NULLPROC;pp = pp->next){
ep = (struct env *)&pp->env;
if(tprintf("%4.4x %-10lx%-10u%-10u %c%c%c %2d %2d %s\n",
FP_SEG(pp),ptol(MK_FP(ep->ss,ep->sp)),pp->stksize,stkutil(pp),
pp->i_state ? 'I' : ' ',
(pp->state & WAITING) ? 'W' : ' ',
(pp->state & SUSPEND) ? 'S' : ' ',
pp->input,pp->output,
pp->name) == EOF)
return 0;
}
if(Curproc != NULLPROC){
ep = (struct env *)&Curproc->env;
tprintf("%4.4x %-10lx%-10u%-10u %c %2d %2d %s\n",
FP_SEG(Curproc),ptol(MK_FP(ep->ss,ep->sp)),Curproc->stksize,
stkutil(Curproc),
Curproc->i_state ? 'I' : ' ',
Curproc->input,Curproc->output,
Curproc->name);
}
#endif /* UNIX */
return 0;
}
int
stkutil(pp)
struct proc *pp;
{
unsigned i;
register int16 *sp;
#ifdef UNIX
if (pp->stack == 0xC0000000) /* can't check system stack, dynamic */
return pp->stksize;
#endif
i = pp->stksize;
for(sp = pp->stack;*sp == STACKPAT && sp < pp->stack + pp->stksize;sp++)
i--;
return i;
}
/* Return number of used words in interrupt stack. Note hardwired value
* for stack size; this is also found in the various .asm files
*/
#ifndef UNIX
static int
chkintstk()
{
register int i;
register int16 *cp;
for(i=512,cp = Intstk; i != 0 && *cp == STACKPAT; cp++)
i--;
return i;
}
#endif
/* Verify that stack pointer for current process is within legal limits;
* also check that no one has dereferenced a null pointer
*/
#ifdef UNIX
static void
__chkstk_internal(spp)
int16 spp;
{
int16 *sp, *sbase, *stop;
sp = &spp; /* close enough for government work */
sbase = Curproc->stack;
if(sbase == NULL)
return; /* Main task -- too hard to check */
stop = sbase + Curproc->stksize;
if(sp < sbase || sp >= stop){
printf("Stack violation, process %s\n",Curproc->name);
printf("SP = %lx, legal stack range [%lx,%lx)\n",
ptol(sp),ptol(sbase),ptol(stop));
fflush(stdout);
killself();
}
}
#endif
void
chkstk()
{
#ifdef UNIX
__chkstk_internal(0); /* must have an argument to take address of */
#else
int16 *sbase;
int16 *stop;
int16 *sp;
#ifdef MULTITASK
extern int Nokeys; /* indicates we are shelled out [pc.c]*/
#endif
sp = MK_FP(_SS,_SP);
if(_SS == _DS){
/* Probably in interrupt context */
return;
}
sbase = Curproc->stack;
if(sbase == NULL)
return; /* Main task -- too hard to check */
stop = sbase + Curproc->stksize;
if(sp < sbase || sp >= stop){
printf("Stack violation, process %s\n",Curproc->name);
printf("SP = %lx, legal stack range [%lx,%lx)\n",
ptol(sp),ptol(sbase),ptol(stop));
fflush(stdout);
killself();
}
if(*(unsigned short *)NULL != oldNull){
#ifdef MULTITASK
if(!Nokeys) /* don't complain if we are shelled out */
#endif
printf("WARNING: Location 0 smashed, process %s\n",Curproc->name);
*(unsigned short *)NULL = oldNull;
fflush(stdout);
}
#endif /* UNIX */
}
/* Machine-dependent initialization of a task */
void
psetup(pp,iarg,parg1,parg2,pc)
struct proc *pp; /* Pointer to task structure */
int iarg; /* Generic integer arg */
void *parg1; /* Generic pointer arg #1 */
void *parg2; /* Generic pointer arg #2 */
void (*pc) __ARGS((int,void *,void *)); /* Initial execution address */
{
register int *stktop;
#ifndef UNIX
register struct env *ep;
#endif
/* Set up stack to make it appear as if the user's function was called
* by killself() with the specified arguments. When the user returns,
* killself() automatically cleans up.
*
* First, push args on stack in reverse order, simulating what C
* does just before it calls a function.
*/
stktop = (int *)(pp->stack + pp->stksize);
#ifdef LINUX
*--stktop = 0; /* dummy stack frame to terminate backtrace */
*--stktop = 0;
#ifdef LITTLE_ENDIAN
*--stktop = (((unsigned long) parg2 & 0xFFFF0000) >> 16) & 0x0000FFFF;
*--stktop = ((unsigned long) parg2 & 0x0000FFFF);
*--stktop = (((unsigned long) parg1 & 0xFFFF0000) >> 16) & 0x0000FFFF;
*--stktop = ((unsigned long) parg1 & 0x0000FFFF);
*--stktop = (((unsigned long) iarg & 0xFFFF0000) >> 16) & 0x0000FFFF;
*--stktop = ((unsigned long) iarg & 0x0000FFFF);
*--stktop = (((unsigned long) killself & 0xFFFF0000) >> 16) & 0x0000FFFF;
*--stktop = ((unsigned long) killself & 0x0000FFFF);
#else
*--stktop = ((unsigned long) parg2 & 0x0000FFFF);
*--stktop = (((unsigned long) parg2 & 0xFFFF0000) >> 16) & 0x0000FFFF;
*--stktop = ((unsigned long) parg1 & 0x0000FFFF);
*--stktop = (((unsigned long) parg1 & 0xFFFF0000) >> 16) & 0x0000FFFF;
*--stktop = ((unsigned long) iarg & 0x0000FFFF);
*--stktop = (((unsigned long) iarg & 0xFFFF0000) >> 16) & 0x0000FFFF;
*--stktop = ((unsigned long) killself & 0x0000FFFF);
*--stktop = (((unsigned long) killself & 0xFFFF0000) >> 16) & 0x0000FFFF;
#endif
#else /* UNIX */
#ifdef LARGEDATA
*--stktop = FP_SEG(parg2);
#endif
*--stktop = FP_OFF(parg2);
#ifdef LARGEDATA
*--stktop = FP_SEG(parg1);
#endif
*--stktop = FP_OFF(parg1);
*--stktop = iarg;
/* Now push the entry address of killself(), simulating the call to
* the user function.
*/
#ifdef LARGECODE
*--stktop = FP_SEG(killself);
#endif
*--stktop = FP_OFF(killself);
#endif
/* Set up task environment. Note that for Turbo-C, the setjmp
* sets the interrupt enable flag in the environment so that
* interrupts will be enabled when the task runs for the first time.
* Note that this requires newproc() to be called with interrupts
* enabled!
*/
setjmp(pp->env);
#ifdef UNIX
_SP(pp) = stktop;
_BP(pp) = stktop;
_PC(pp) = pc;
#else
ep = (struct env *)&pp->env;
ep->ss = FP_SEG(stktop);
ep->sp = FP_OFF(stktop);
ep->cs = FP_SEG(pc); /* Doesn't hurt in small model */
ep->ip = FP_OFF(pc);
#endif
/* Task initially runs with interrupts on */
pp->i_state = 1;
}
unsigned
phash(event)
void *event;
{
register unsigned x;
/* Fold the two halves of the pointer */
#ifdef UNIX
x = (unsigned) event;
#else
x = FP_SEG(event) ^ FP_OFF(event);
#endif
/* If PHASH is a power of two, this will simply mask off the
* higher order bits
*/
return x % PHASH;
}